package com.kilograms.lensflareit;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class ImageEditor extends Activity implements OnClickListener {

	private static String TAG = "com.kilograms.lensflareit";
	
	private static int imageNumber = 0;
	private static final String lensflareDirectoryPath = "Lensflared";
	
	// Views
	private ImageView iv;
	private Button saveBtn;
	private Button cancelBtn;
	private Button lensflareBtn;
	
	// Bitmaps
	private Bitmap initialImage; // The image passed from the bundle
	private Bitmap flareOverlay; // The image to use as an overlay (transparent .png with lensflare)
	private Bitmap flaredImage;  // The finished lensflared image made from 'putting flareOverlay on top of initialImage'
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.image_editor_layout);
		
		saveBtn = (Button) findViewById(R.id.saveBtn);
		cancelBtn = (Button) findViewById(R.id.cancelBtn);
		lensflareBtn = (Button) findViewById(R.id.lensflareBtn);
		
		saveBtn.setOnClickListener(this);
		cancelBtn.setOnClickListener(this);
		lensflareBtn.setOnClickListener(this);
		
		// Get extras and set our ImageView to show the image 
		Intent i = getIntent();
		Bundle extras = i.getExtras();
		try {
			String filePath = extras.getString("filePath");
			initialImage = BitmapFactory.decodeFile(filePath);
			
			iv = (ImageView) findViewById(R.id.image);
			iv.setImageBitmap(initialImage);
		} catch (Exception e) {
			Log.v(TAG, "Could not get image");
		}
		
		// Set our flareOverlay
		flareOverlay = BitmapFactory.decodeResource(getResources(), R.drawable.flare1);
	}

	/**
	 * Handle button clicks
	 */
	public void onClick(View v) {
		if(v==saveBtn) {
			Log.v(TAG, "saveBtn clicked");
			saveLensflaredImage();
		} else if(v==cancelBtn) {
			Log.v(TAG, "cancelBtn clicked");
			setFlaredImageToImageView();
		} else if(v==lensflareBtn) {
			Log.v(TAG, "lensflareBtn clicked");
			flaredImage = createLensflaredImage(initialImage, flareOverlay);
			iv.setImageBitmap(flaredImage);
		}
	}
	
	/**
	 * Saves <code>flaredImage</code> to the directory 'Lensflared' in the standard 'Pictures' folder.
	 * Takes care of finding the next available file name and that the 'Lensflared' directory actually exists.
	 * If everything goes well it tells Android's media scanner to scan the file so that it will show up in
	 * Android's gallery application of choice.
	 */
	private void saveLensflaredImage() {
		File lensflareDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), lensflareDirectoryPath);
		File file;
		
		boolean okay = true;
		
		// Check if our directory exists
		if(!lensflareDirectory.exists()) {
			if(!lensflareDirectory.mkdirs()) {
				Log.v(TAG, "Could not create image path.");
				okay = false;
			}
		} else {
			Log.v(TAG, "Image path exists");
		}
		
		// Find the next available file name
		Log.v(TAG, "Getting next available file name");
		file = new File(lensflareDirectory, createFileName(imageNumber));
		while(file.exists() && imageNumber < 1000) {
			Log.v(TAG, "File exists: " + file + ". Trying next id");
			file  = new File(lensflareDirectory, createFileName(++imageNumber));
		}
		Log.v(TAG, "Loop finished. File name: " + file);
		
		// Try to create the file
		try {
			if(!file.createNewFile()) {
				Log.v(TAG, "Could not create file");
				okay = false;
			}
		} catch (IOException e) {
			Log.v(TAG, "Error creating file" + file);
			Log.w("ExternalStorage", "Error creating " + file, e);
			okay = false;
		}
		
		// If the file was created, write our lensflared image to the file
		if(okay) {
			Log.v(TAG, "File creation okay. Writing file...");
			try {
				ByteArrayOutputStream os = new ByteArrayOutputStream();
				flaredImage.compress(Bitmap.CompressFormat.PNG, 100, os);
				FileOutputStream fo = new FileOutputStream(file);
				fo.write(os.toByteArray());
				Toast.makeText(this, "Succesfully saved", Toast.LENGTH_SHORT).show();
				Log.v(TAG, "File successfully saved");
				
				// If everything went well, tell the media scanner to scan the file
		        MediaScannerConnection.scanFile(this,
		                new String[] { file.toString() }, null,
		                new MediaScannerConnection.OnScanCompletedListener() {
		            public void onScanCompleted(String path, Uri uri) {
		                Log.i("ExternalStorage", "Scanned " + path + ":");
		                Log.i("ExternalStorage", "-> uri=" + uri);
		            }
		        });
			} catch (IOException e) {
				Toast.makeText(this, "Could not save the file", Toast.LENGTH_SHORT).show();
				Log.v(TAG, "Error writing file " + file);
				Log.w("ExternalStorage", "Error writing " + file, e);
			}
		}
	}
	
	/**
	 * Helper method for setting <code>flaredImage</code> to our imageView (iv)
	 * so we can check that flaredImage is set properly
	 */
	private void setFlaredImageToImageView() {
		iv.setImageBitmap(flaredImage);
	}
	
	/**
	 * Creates a filename given the <code>imageNumber</code>
	 * @param imageNumber
	 * @return Filename
	 */
	private String createFileName(int imageNumber) {
		return "lensflare" + imageNumber + ".png";
	}

	/**
	 * Creates a <code>Bitmap</code> with <code>overlay</code> on top of <code>background</code>.
	 * @param background The image to lensflare
	 * @param overlay The overlay to put on top of <code>background</code>
	 * @return New image with lensflare
	 */
	private Bitmap createLensflaredImage(Bitmap background, Bitmap overlay) {
		Log.v(TAG, "createLensflaredImage()");
		
		Bitmap temp = Bitmap.createBitmap(background.getWidth(), background.getHeight(), background.getConfig());
		
		Canvas imageWithFlare = new Canvas(temp);
		imageWithFlare.drawBitmap(background, new Matrix(), null);
		imageWithFlare.drawBitmap(flareOverlay, new Matrix(), null);
		
		return temp;
	}
}
